<?php

namespace app\admin\controller\workorder;

use think\Db;
use fast\Date;
use app\common\controller\Backend;

/**
 * 工单管理
 */
class Statistics extends Backend
{
    public function _initialize()
    {
        parent::_initialize();
    }

    public function index()
    {
        if ($this->request->isAjax()) {
            $this->success('', null, $this->dateOrderTrend());
        }

        // 沟通处理中
        $pending_wo_total = Db::name('workorder_orders')
            ->where('status', 'in', '2,3')
            ->where('deletetime', null)
            ->count('id');

        // 未结单
        $open_wo_total = Db::name('workorder_orders')
            ->where('status', 'in', '0,1,2,3')
            ->where('deletetime', null)
            ->count('id');

        // 待分派
        $assign_wo_total = Db::name('workorder_orders')->where('status', '0')->where('deletetime', null)->count('id');

        // 解决率和满意度
        $evaluate = Db::name('workorder_evaluate')
            ->alias('e')
            ->field('e.stars,e.solved')
            ->join('workorder_orders o', 'o.id=e.order_id')
            ->where('o.deletetime', null)
            ->select();

        $not_evaluated = Db::name('workorder_orders')->where('status', '4')->where('deletetime', null)->count('id');

        $solved_temp = [0, 0];
        $stars_temp  = [0, 0, 0, 0, 0];
        foreach ($evaluate as $item) {
            if ($item['solved'] == 0) {
                $solved_temp[0]++;
            } else {
                $solved_temp[1]++;
            }

            $stars_temp[($item['stars'] - 1)]++;
        }

        if ($solved_temp[0] > 0) {
            $solved[] = [
                'value' => $solved_temp[0],
                'name'  => __('unresolved')
            ];
        }
        if ($solved_temp[1] > 0) {
            $solved[] = [
                'value' => $solved_temp[1],
                'name'  => __('resolved')
            ];
        }

        for ($i = 0; $i < 5; $i++) {
            if ($stars_temp[$i] > 0) {
                $stars[] = [
                    'value' => $stars_temp[$i],
                    'name'  => __('star ' . $i)
                ];
            }
        }
        if ($not_evaluated > 0) {
            $stars[] = [
                'value' => $not_evaluated,
                'name'  => __('Not evaluated')
            ];

            $solved[] = [
                'value' => $not_evaluated,
                'name'  => __('Not evaluated')
            ];
        }

        if (!isset($stars)) {
            $stars[] = [
                'value' => 0,
                'name'  => __('No data available')
            ];
        }

        if (!isset($solved)) {
            $solved[] = [
                'value' => 0,
                'name'  => __('No data available')
            ];
        }

        $average_time['solution'] = Db::name('workorder_time_statistics')
            ->alias('s')
            ->join('workorder_orders o', 'o.id=s.order_id')
            ->where('o.deletetime', null)
            ->where('s.type', 0)
            ->where('s.time_consum', '>', 0)
            ->avg('s.time_consum');

        $average_time['response'] = Db::name('workorder_time_statistics')
            ->alias('s')
            ->join('workorder_orders o', 'o.id=s.order_id')
            ->where('o.deletetime', null)
            ->where('s.type', 'in', '1,2')
            ->where('s.time_consum', '>', 0)
            ->avg('s.time_consum');

        $average_time['first_response'] = Db::name('workorder_time_statistics')
            ->alias('s')
            ->join('workorder_orders o', 'o.id=s.order_id')
            ->where('o.deletetime', null)
            ->where('s.type', 2)
            ->where('s.time_consum', '>', 0)
            ->avg('s.time_consum');
        foreach ($average_time as $key => $value) {
            if ($value) {
                $h                              = floor($value / 3600);
                $m                              = ceil(($value % 3600) / 60);
                $average_time[$key]             = [
                    'value'    => __('%s hour %s minute', [$h, $m]),
                    'progress' => ceil($h . '.' . $m)
                ];
                $average_time[$key]['progress'] = ($average_time[$key]['progress'] > 100) ? 100 : $average_time[$key]['progress'];
            } else {
                $average_time[$key] = [
                    'value'    => __('No data'),
                    'progress' => 0
                ];
            }
        }

        $prefix = config('database.prefix');

        // 类别工单量TOP10
        $sql                      = "SELECT wc.id,wc.name,
                (SELECT count(id) FROM {$prefix}workorder_orders wo WHERE wo.category_id=wc.id AND wo.deletetime IS NULL) as order_quantity
                FROM {$prefix}workorder_category wc WHERE wc.pid>0 AND wc.deletetime IS NULL ORDER BY order_quantity DESC";
        $workorder_category_top10 = Db::query($sql);

        $order_quantity_sum = array_sum(array_map(function ($val) {
            return $val['order_quantity'];
        }, $workorder_category_top10));
        foreach ($workorder_category_top10 as $index => $item) {
            if ($index <= 9) {
                if ($item['order_quantity'] > 0) {
                    $workorder_category_top10[$index]['progress'] = round(($item['order_quantity'] / $order_quantity_sum) * 100, 2);
                } else {
                    $workorder_category_top10[$index]['progress'] = 0;
                }
            } else {
                unset($workorder_category_top10[$index]);
            }
        }

        $workorder_engineers_top10 = Db::name('workorder_engineers')
            ->field('id,title,work_order_quantity')
            ->where('deletetime', null)
            ->where('status', '1')
            ->order('work_order_quantity desc')
            ->limit(10)
            ->select();

        $avg_response_time_top10 = Db::name('workorder_engineers')
            ->field('id,title,avg_response_time')
            ->where('deletetime', null)
            ->where('status', '1')
            ->order('avg_response_time desc')
            ->limit(10)
            ->select();
        foreach ($avg_response_time_top10 as $index => $item) {
            if ($item['avg_response_time'] > 0) {
                $h                                                    = floor($item['avg_response_time'] / 3600);
                $m                                                    = ceil(($item['avg_response_time'] % 3600) / 60);
                $avg_response_time_top10[$index]['avg_response_time'] = __('%s hour %s minute', [$h, $m]);
            } else {
                $avg_response_time_top10[$index]['avg_response_time'] = __('No data');
            }
        }

        $this->view->assign([
            'wo_total'                  => Db::name('workorder_orders')->where('deletetime', null)->count('id'),
            'pending_wo_total'          => $pending_wo_total,
            'open_wo_total'             => $open_wo_total,
            'assign_wo_total'           => $assign_wo_total,
            'average_time'              => $average_time,
            'workorder_category_top10'  => $workorder_category_top10,
            'workorder_engineers_top10' => $workorder_engineers_top10,
            'avg_response_time_top10'   => $avg_response_time_top10
        ]);
        $this->assignconfig([
            'orderTrend' => $this->dateOrderTrend(),
            'solved'     => $solved,
            'stars'      => $stars
        ]);
        return $this->view->fetch();
    }

    /**
     * 日期范围内的订单趋势
     */
    public function dateOrderTrend()
    {
        $date = $this->request->request('date');
        if ($date) {
            $date = explode(' - ', $date);
            $date = array_map("strtotime", $date);
        } else {
            $date[0] = Date::unixtime('day', -6);
            $date[1] = Date::unixtime('day', 0, 'end');
        }

        if ($date[0] >= $date[1]) {
            $this->error(__('The start time must be less than the end time'));
        }

        $orders = Db::name('workorder_orders')
            ->field("id,createtime")
            ->where('deletetime', null)
            ->where('createtime', 'BETWEEN', implode(',', $date))
            ->order('createtime asc')
            ->select();

        $temp    = [];
        $columns = [];
        $data    = [];

        if (($date[1] - $date[0]) <= 86400) {
            // 时间数组准备
            for ($i = 0; $i <= 23; $i++) {
                $temp[($i < 10 ? '0' . $i : $i) . ':00'] = 0;
            }

            // 累计各个时间的订单量
            foreach ($orders as $item) {
                $createtime = date('H', $item['createtime']) . ':00';
                $temp[$createtime]++;
            }
        } else {
            // 日期数组准备
            do {
                $temp[date('Y-m-d', $date[0])] = 0;
                $date[0]                       = $date[0] + 86400;
            } while ($date[0] < $date[1]);

            // 累计各个日期的订单量
            foreach ($orders as $item) {
                $createtime = date('Y-m-d', $item['createtime']);
                $temp[$createtime]++;
            }
        }

        foreach ($temp as $index => $item) {
            $columns[] = $index;
            $data[]    = $item;
        }

        return [
            'columns' => $columns,
            'data'    => $data,
            'sum'     => array_sum($data)
        ];
    }

}